'use strict';
const crypto = require('crypto');

// JWT密钥（生产环境应该保存在安全的配置中）
const JWT_SECRET = 'referee-training-app-secret-key';
// token有效期（秒）
const TOKEN_EXPIRATION = 60 * 60 * 24 * 7; // 7天
// 刷新阈值（秒）- 当剩余有效期小于此值时触发刷新
const REFRESH_THRESHOLD = 60 * 60 * 24; // 1天

/**
 * 生成JWT token
 * @param {Object} payload 有效载荷
 * @returns {String} JWT token
 */
function generateToken(payload) {
    // 确保payload中包含过期时间
    const now = Math.floor(Date.now() / 1000);
    
    // 设置标准JWT字段
    const tokenPayload = {
        ...payload,
        iat: now, // 签发时间
        exp: now + TOKEN_EXPIRATION // 过期时间
    };
    
    // JWT header
    const header = {
        alg: 'HS256',
        typ: 'JWT'
    };
    
    // 将header转为base64
    const base64Header = Buffer.from(JSON.stringify(header)).toString('base64')
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=/g, '');
    
    // 将payload转为base64
    const base64Payload = Buffer.from(JSON.stringify(tokenPayload)).toString('base64')
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=/g, '');
    
    // 计算签名
    const unsignedToken = `${base64Header}.${base64Payload}`;
    const signature = crypto.createHmac('sha256', JWT_SECRET)
        .update(unsignedToken)
        .digest('base64')
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=/g, '');
    
    // 完整的JWT token
    return `${unsignedToken}.${signature}`;
}

/**
 * 解析JWT token
 * @param {String} token JWT token
 * @returns {Object|null} 解析后的payload或null（如果无效）
 */
function parseToken(token) {
    if (!token) return null;
    
    try {
        // 分割token
        const parts = token.split('.');
        if (parts.length !== 3) return null;
        
        // 解码payload
        const payload = parts[1];
        const decodedPayload = Buffer.from(
            payload.replace(/-/g, '+').replace(/_/g, '/'),
            'base64'
        ).toString('utf8');
        
        return JSON.parse(decodedPayload);
    } catch (error) {
        console.error('Token解析失败:', error);
        return null;
    }
}

/**
 * 验证token签名
 * @param {String} token JWT token
 * @returns {Boolean} 签名是否有效
 */
function verifySignature(token) {
    if (!token) return false;
    
    try {
        // 分割token
        const parts = token.split('.');
        if (parts.length !== 3) return false;
        
        const [header, payload, signature] = parts;
        
        // 重新计算签名
        const unsignedToken = `${header}.${payload}`;
        const expectedSignature = crypto.createHmac('sha256', JWT_SECRET)
            .update(unsignedToken)
            .digest('base64')
            .replace(/\+/g, '-')
            .replace(/\//g, '_')
            .replace(/=/g, '');
        
        // 比较签名
        return signature === expectedSignature;
    } catch (error) {
        console.error('Token签名验证失败:', error);
        return false;
    }
}

/**
 * 验证token是否有效
 * @param {String} token JWT token
 * @returns {Object} 验证结果 {valid, message, payload, needRefresh}
 */
function verifyToken(token) {
    if (!token) {
        return {
            valid: false,
            message: 'Token不存在',
            payload: null,
            needRefresh: false
        };
    }
    
    // 验证签名
    if (!verifySignature(token)) {
        return {
            valid: false,
            message: 'Token签名无效',
            payload: null,
            needRefresh: false
        };
    }
    
    // 解析payload
    const payload = parseToken(token);
    if (!payload) {
        return {
            valid: false,
            message: 'Token格式错误',
            payload: null,
            needRefresh: false
        };
    }
    
    // 验证过期时间
    const now = Math.floor(Date.now() / 1000);
    if (!payload.exp || now > payload.exp) {
        return {
            valid: false,
            message: 'Token已过期',
            payload,
            needRefresh: false
        };
    }
    
    // 检查是否需要刷新
    const timeRemaining = payload.exp - now;
    const needRefresh = timeRemaining < REFRESH_THRESHOLD;
    
    return {
        valid: true,
        message: 'Token有效',
        payload,
        needRefresh
    };
}

/**
 * 刷新token
 * @param {String} token 原始token
 * @returns {Object} 刷新结果 {success, token, message}
 */
function refreshToken(token) {
    const verifyResult = verifyToken(token);
    
    // 如果token完全无效，则拒绝刷新
    if (!verifyResult.valid && !verifyResult.payload) {
        return {
            success: false,
            token: null,
            message: '无效的token，无法刷新'
        };
    }
    
    // 即使token已过期，仍可以刷新（只要在合理时间内）
    const now = Math.floor(Date.now() / 1000);
    const payload = verifyResult.payload;
    
    // 检查过期时间是否在可接受范围内（例如过期不超过7天）
    if (payload.exp && now - payload.exp > TOKEN_EXPIRATION) {
        return {
            success: false,
            token: null,
            message: 'Token过期时间过长，请重新登录'
        };
    }
    
    // 复制原payload，但不包含exp和iat（刷新时会重新生成）
    const { exp, iat, ...newPayload } = payload;
    
    // 生成新token
    const newToken = generateToken(newPayload);
    
    return {
        success: true,
        token: newToken,
        message: 'Token刷新成功'
    };
}

module.exports = {
    generateToken,
    verifyToken,
    parseToken,
    refreshToken
}; 